package com.datang.litejvm.engin;

import com.datang.litejvm.clz.Method;

import java.util.ArrayList;
import java.util.List;
import java.util.Stack;

/**
 * @author: 顶风少年
 * @Description: 执行引擎
 * @date: 15:19 2022/6/16
 **/
public class ExecutorEngine {

    /**
     * @author: 顶风少年
     * @Description: 栈
     * @date: 15:41 2022/6/16
     **/
    private Stack<StackFrame> stack = new Stack<StackFrame>();


    public void execute(Method mainMethod) {
        //创建main栈帧
        StackFrame stackFrame = StackFrame.create(mainMethod);
        //入栈
        stack.push(stackFrame);
        //接下来就是对栈做操作了,入栈,出栈
        while (!stack.isEmpty()) {
            //拿到栈顶栈帧
            StackFrame frame = stack.peek();
            //执行栈帧
            ExecutionResult result = frame.execute();
            //暂停,并运行新的栈帧.有函数调用了
            if (result.isPauseAndRunNewFrame()) {
                //下一个method
                Method nextMethod = result.getNextMethod();
                //形成新的栈帧
                StackFrame nextFrame = StackFrame.create(nextMethod);
                nextFrame.setCallerFrame(frame);
                setupFunctionCallParams(frame, nextFrame);
                //将新的栈帧也入栈
                stack.push(nextFrame);
            } else {
                //出栈
                stack.pop();
            }
        }
    }

    /**
     * @author: 顶风少年
     * @Description: 给下个调用方法设置参数
     * @date: 16:07 2022/6/16
     **/
    private void setupFunctionCallParams(StackFrame currentFrame, StackFrame nextFrame) {
        Method nextMethod = nextFrame.getMethod();
        //获取参数列表
        List<String> parameterList = nextMethod.getParameterList();
        List<JavaObject> values = new ArrayList<>();
        //要添加 this
        int paramNum = parameterList.size() + 1;

        while (paramNum > 0) {
            values.add(currentFrame.getOperandStack().pop());
            paramNum--;
        }

        List<JavaObject> params = new ArrayList<>();
        for (int i = values.size() - 1; i >= 0; i--) {
            params.add(values.get(i));
        }
        //设置局部变量表
        nextFrame.setLocalVariableTable(params);
    }

}
